﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using StaffDotNet.CollapsiblePanel;

namespace Camelot
{
    public partial class SearchOptions : BaseUserControl
    {
        public event EventHandler<SearchEventArgs> Search;
        public event EventHandler<ContentTypeChangedArgs> ContentTypeChanged;

        public new SPSite Site { get; set; }

        public SearchOptions()
        {
            this.InitializeComponent();
            this.InitializeEvents();
            this.InitializeControls();
            this.InitializeMemberFields();
        }

        private List<BaseTemplate> BaseTemplateItems { get; set; }

        private void InitializeMemberFields()
        {
            this.BaseTemplateItems = new List<BaseTemplate>
                                         {
                                             new BaseTemplate("Generic list", SPBaseType.GenericList),
                                             new BaseTemplate("Document library", SPBaseType.DocumentLibrary),
                                             new BaseTemplate("Unused", SPBaseType.Unused),
                                             new BaseTemplate("Discussion board", SPBaseType.DiscussionBoard),
                                             new BaseTemplate("Survey", SPBaseType.Survey),
                                             new BaseTemplate("Issue", SPBaseType.Issue),
                                             new BaseTemplate("Unspecified", SPBaseType.UnspecifiedBaseType)
                                         };
            this.Site = new SPSite(this.webUrlTextBox.Text);
        }

        private void InitializeEvents()
        {
            this.ContentTypeChanged += SearchOptionsContentTypeChanged;
        }

        private void SearchOptionsContentTypeChanged(object sender, ContentTypeChangedArgs e)
        {
                
            if (e.Item == null)
            {
                this.availableFieldsList.DataSource = null;
                this.availableFieldsList.Items.Clear();
                this.selectedFieldslist.Items.Clear();
                
                return;
            }


            IOrderedEnumerable<SPField> fields;
            
            if (e.Item.ContentType == null)
            {

                fields = (from f in this.Site.RootWeb.Fields.Cast<SPField>()
                          orderby f.InternalName
                          select f);
            }
            else
            {
                fields = (from f in e.Item.ContentType.Fields.Cast<SPField>()
                          orderby f.InternalName
                          select f);
            }

            
            this.availableFieldsList.DataSource = fields.ToList();
            this.availableFieldsList.DisplayMember = "InternalName";
        }

        private void InitializeControls()
        {
            this.fieldPanel.PanelState = PanelStateOptions.Expanded;
            this.selectedFieldslist.DisplayMember = "InternalName";
        }


        protected override void OnLoad(EventArgs e)
        {
            if (this.ParentForm != null && this.Site != null)
            {
                this.InitializeContentTypes();
                this.InitializeListTemplates();
                this.InitializeBaseTemplates();
                this.InitializeSearchScopes();
            }
        }

        private void InitializeBaseTemplates()
        {
            this.baseTemplateDropDown.SelectedValueChanged += OnBaseTemplateDropDownSelectedValueChanged;
            this.baseTemplateDropDown.DisplayMember = "Name";
            this.baseTemplateDropDown.DataSource = this.BaseTemplateItems;
            this.baseTemplateDropDown.SelectedItem = null;
        }

        private void InitializeSearchScopes()
        {
            this.searchScopeDropDown.SelectedItem = this.searchScopeDropDown.Items[0];
        }

        private void InitializeListTemplates()
        {
            var templates =
                from t in this.Site.RootWeb.ListTemplates.Cast<SPListTemplate>()
                orderby t.Name
                select t;

            this.listTemplatesDropDown.SelectedValueChanged += OnListTemplatesDropDownSelectedValueChanged;
            this.listTemplatesDropDown.DisplayMember = "Name";
            this.listTemplatesDropDown.DataSource = templates.ToList();
            this.listTemplatesDropDown.SelectedItem = null;
        }

        private void OnListTemplatesDropDownSelectedValueChanged(object sender, EventArgs e)
        {
            if (this.listTemplatesDropDown.SelectedItem == null)
            {
                return;
            }

            this.baseTemplateDropDown.SelectedItem = null;
        }

        private void OnBaseTemplateDropDownSelectedValueChanged(object sender, EventArgs e)
        {
            if (this.baseTemplateDropDown.SelectedItem == null)
            {
                return;
            }

            this.listTemplatesDropDown.SelectedItem = null;
        }

        private void InitializeContentTypes()
        {
            IEnumerable<ContentTypeItem> contentTypes = this.GetContentTypes(string.Empty);
            InitializeContentTypeGroups(contentTypes);

            List<ContentTypeItem> contentTypeItems = contentTypes.ToList();
            contentTypeItems.Insert(0, new ContentTypeItem("{None}", null));
            this.contentTypeDropDown.SelectedValueChanged += ContentTypeDropDownSelectedValueChanged;
            this.contentTypeDropDown.DataSource = contentTypeItems;
            this.contentTypeDropDown.DisplayMember = "DisplayName";            
        }

        private IEnumerable<ContentTypeItem> GetContentTypes(string groupName)
        {
            if (string.IsNullOrEmpty(groupName))
            {
                return from c in Site.RootWeb.AvailableContentTypes.Cast<SPContentType>()
                       orderby c.Name
                       select new ContentTypeItem(c.Name, c);
            }
            
            return from c in Site.RootWeb.AvailableContentTypes.Cast<SPContentType>()
                   where c.Group.Equals(groupName, StringComparison.CurrentCultureIgnoreCase)
                   select new ContentTypeItem(c.Name, c);
        }

        private void InitializeContentTypeGroups(IEnumerable<ContentTypeItem> contentTypes)
        {
            var groups =
                from c in contentTypes
                group c by c.ContentType.Group into g
                select  g.Key;

            var list = groups.ToList();
            list.Insert(0, "All");

            this.contentTypeGroupDropDown.DataSource = list;
            this.contentTypeGroupDropDown.SelectedIndex = 0;

            this.contentTypeGroupDropDown.SelectedValueChanged += ContentTypeGroupDropDownSelectedValueChanged;
        }

        private void ContentTypeGroupDropDownSelectedValueChanged(object sender, EventArgs e)
        {
            string item = this.contentTypeGroupDropDown.SelectedItem as string;
            if (item == "All")
            {
                item = string.Empty;
            }

            this.contentTypeDropDown.DataSource = this.GetContentTypes(item).ToList();
            this.contentTypeDropDown.SelectedItem = null;
        }

        private void ContentTypeDropDownSelectedValueChanged(object sender, EventArgs e)
        {
            if (this.ContentTypeChanged != null)
            {
                this.ContentTypeChanged(this, new ContentTypeChangedArgs(this.contentTypeDropDown.SelectedItem as ContentTypeItem));
            }
        }

        private void SearchButtonOnClick(object sender, EventArgs e)
        {
            ContentTypeItem contentTypeItem = (ContentTypeItem)contentTypeDropDown.SelectedItem;
            SPContentType contentType = contentTypeItem != null ? contentTypeItem.ContentType : null;
            SearchCriteria searchCriteria = new SearchCriteria
                                                {
                                                    WebUrl = new Uri(this.webUrlTextBox.Text),
                                                    ContentType = contentType
                                                };

            if (this.baseTemplateDropDown.SelectedItem != null)
            {
                searchCriteria.BaseTemplate = (BaseTemplate)this.baseTemplateDropDown.SelectedItem;
            }
            else if (this.listTemplatesDropDown.SelectedItem != null)
            {
                searchCriteria.ListTemplate = (SPListTemplate)this.listTemplatesDropDown.SelectedItem;
            }

            if (this.searchScopeDropDown.SelectedIndex <= 2)
            {
                searchCriteria.SearchScope = (string)this.searchScopeDropDown.SelectedItem;
            }
            else
            {
                searchCriteria.SearchScope = string.Empty;
            }

            if (this.selectedFieldslist.Items.Count > 0)
            {
                StringBuilder viewFields = new StringBuilder();
                foreach (SPField field in this.selectedFieldslist.Items)
                {
                    viewFields.Append(string.Format("<FieldRef Name='{0}' />", field.InternalName));
                }

                searchCriteria.ViewFields = viewFields.ToString();
            }

            if (this.Search != null)
            {
                this.Search(this, new SearchEventArgs(searchCriteria));
            }
        }

        private void FieldButtonOnClick(object sender, EventArgs e)
        {
            if (sender == this.addAllButton)
            {
                this.selectedFieldslist.Items.Clear();
                this.selectedFieldslist.Items.AddRange(this.availableFieldsList.Items);
                return;
            }

            if (sender == this.addFieldButton && this.availableFieldsList.SelectedItems.Count > 0)
            {
                foreach (SPField field in this.availableFieldsList.SelectedItems)
                {
                    if (!this.selectedFieldslist.Items.Contains(field))
                    {
                        this.selectedFieldslist.Items.Add(field);
                    }
                }

                return;                
            }

            if(sender == this.removeAllButton)
            {
                this.selectedFieldslist.Items.Clear();
                return;                
            }

            if(sender == this.removeSelectedButton)
            {
                for (int i = this.selectedFieldslist.SelectedItems.Count - 1; i >= 0; i--)
                {
                    SPField item = (SPField) this.selectedFieldslist.SelectedItems[i];
                    this.selectedFieldslist.Items.Remove(item);
                }
                return;
            }
        }
    }
}
